home *** CD-ROM | disk | FTP | other *** search
- /*
- * samples.c: Routines for Ptmid to deal with samples. The use of these
- * routines makes it easy to add support for further sample formats.
- *
- * author: Andrew Scott (c)opyright 1994
- *
- * date: 30/6/1994
- */
- #include <stdio.h>
- #include <string.h>
- #include "ptmid.h"
- #include "samples.h"
-
- /** Define VC enumerated type to specify sort of VOC-chunk to look for **/
- enum VC { VC_term = 0, VC_voc, VC_cnt, VC_spc, VC_mrk, VC_txt,
- VC_rep, VC_enr };
-
- /*
- * CatFn: Given two filenames, will return a pointer to a copy of them
- * concatenated together.
- *
- * date: 30/6/1994
- */
- Sz CatFn(Sz fnA, Sz fnB)
- {
- static Fn fnBuff;
- Sz szT = fnBuff;
-
- while (*szT = *(fnA++))
- szT++;
- while (*(szT++) = *(fnB++));
- return fnBuff;
- }
-
- /*
- * FIsvoc: Given a file pointer, will return NZ if the file is a VOC
- * file.
- *
- * date: 30/6/1994
- */
- int FIsvoc(FILE *pfile)
- {
- char rgbClbuff[20];
-
- fseek(pfile, 0, SEEK_SET);
- if (fread(rgbClbuff, 20, 1, pfile) == 0)
- return 0;
- return !strncmp(rgbClbuff, "Creative Voice File\32", 20);
- }
-
- /*
- * FIswav: Given a file pointer, will return NZ if the file is a WAV
- * file.
- *
- * date: 1/7/1994
- */
- int FIswav(FILE *pfile)
- {
- char rgbRiffbuff[12];
-
- fseek(pfile, 0, SEEK_SET);
- if (fread(rgbRiffbuff, 12, 1, pfile) == 0)
- return 0;
- return !strncmp(rgbRiffbuff, "RIFF", 4) &&
- !strncmp(rgbRiffbuff + 8, "WAVE", 4);
- }
-
- /*
- * LongRead: Returns the next long integer from the given file.
- *
- * date: 1/7/1994
- */
- unsigned long LongRead(FILE *pfile)
- {
- unsigned long dw;
-
- dw = getc(pfile);
- dw += (unsigned long) getc(pfile) << 8;
- dw += (unsigned long) getc(pfile) << 16;
- dw += (unsigned long) getc(pfile) << 24;
- return dw;
- }
-
- /*
- * TriRead: Returns the next byte triple from the given file.
- *
- * date: 1/7/1994
- */
- unsigned long TriRead(FILE *pfile)
- {
- unsigned long dw;
-
- dw = getc(pfile);
- dw += (unsigned long) getc(pfile) << 8;
- dw += (unsigned long) getc(pfile) << 16;
- return dw;
- }
-
- /*
- * WordRead: Returns the next word from the given file.
- *
- * date: 1/7/1994
- */
- unsigned WordRead(FILE *pfile)
- {
- unsigned w;
-
- w = getc(pfile);
- w += (unsigned) getc(pfile) << 8;
- return w;
- }
-
- /*
- * Govoc: Given a VOC-file and a chunk-tag, will advance the file to
- * the start of the chunk if it exists and return NZ, else will return Z.
- *
- * date: 1/7/1994
- */
- int Govoc(FILE *pfile, enum VC vcChunk)
- {
- int bT;
- unsigned long len;
-
- fseek(pfile, 20, SEEK_SET);
- len = WordRead(pfile);
- fseek(pfile, len, SEEK_SET);
- bT = getc(pfile);
- while (EOF != bT && 0 != bT && bT != vcChunk) {
- len = TriRead(pfile);
- if (0 < len)
- fseek(pfile, len, SEEK_CUR);
- bT = getc(pfile);
- }
- return bT == vcChunk;
- }
-
- /*
- * Gowav: Given a wave-file and a chunk-name, will advance the file to
- * the start of the chunk if it exists and return NZ, else will return Z.
- *
- * date: 1/7/1994
- */
- int Gowav(FILE *pfile, Sz szChunk)
- {
- char rgbBuff[4];
- unsigned long len;
-
- fseek(pfile, 12, SEEK_SET);
- fread(rgbBuff, 4, 1, pfile);
- while (!feof(pfile) && strncmp(szChunk, rgbBuff, 4)) {
- len = LongRead(pfile);
- if (fseek(pfile, len, SEEK_CUR) || !fread(rgbBuff, 4, 1, pfile))
- return 0;
- }
- return !feof(pfile);
- }
-
- /*
- * FreqGetFn: Given a sample's filename, will return the frequency of
- * that sample.
- *
- * date: 30/6/1994
- */
- unsigned FreqGetFn(Sz fnSample)
- {
- unsigned freq = C2FREQUENCY;
- int wData;
- FILE *pfile;
-
- pfile = fopen(CatFn(fnSampath, fnSample), "rb"); /** Open file **/
- if (NULL != pfile) {
- if (FIsvoc(pfile)) { /** If a VOC file **/
- fseek(pfile, 20, SEEK_SET);
- if ((wData = getc(pfile)) != EOF &&
- !fseek(pfile, ((long) getc(pfile) << 8) | wData, SEEK_SET) &&
- getc(pfile) == 1) { /*** Go to start of sound info ***/
- getc(pfile); /*** Skip length ***/
- getc(pfile);
- getc(pfile);
- wData = getc(pfile); /*** Get sample rate ***/
- freq = (unsigned) (1000000L / (256 - wData));
- }
- } else if (FIswav(pfile) && Gowav(pfile, "fmt ")) { /** If a WAV file **/
- fseek(pfile, 8, SEEK_CUR); /*** Go to position of freqency ***/
- freq = (unsigned) LongRead(pfile); /*** Get sample rate ***/
- }
- fclose(pfile);
- }
- return freq;
- }
-
- /*
- * LenOutPfileFn: Given an output file and a sample filename, writes the
- * sample to the output file and returns the number of bytes written.
- * If fSignout is NZ, data will be written in signed format, else in
- * unsigned.
- *
- * date: 30/6/1994
- * 1/7/1994 - added WAV format
- * 2/7/1994 - added fSignout
- */
- long LenOutPfileFn(FILE *pfileOut, Sz fnSample, int fSignout)
- {
- FILE *pfileSample;
- long cSample = 0;
-
- pfileSample = fopen(CatFn(fnSampath, fnSample), "rb");
- if (NULL == pfileSample)
- return 0;
- if (FIsvoc(pfileSample)) { /** Is sample file a VOC file? **/
- unsigned long cch;
- int ch;
-
- Govoc(pfileSample, VC_voc);
- cch = TriRead(pfileSample) - 2; /*** Get length ***/
- if (131072 < cch)
- cch = 131072;
- else if (cch & 1) /*** Ensure length is even ***/
- cch &= ~1;
- cSample = cch;
- fseek(pfileSample, 2, SEEK_CUR); /*** Skip rate + compression ***/
- while (cch-- && (ch = getc(pfileSample)) != EOF)
- if (fSignout)
- putc(ch ^ 128, pfileOut); /*** Copy the samples ***/
- else
- putc(ch, pfileOut);
-
- } else if (FIswav(pfileSample)) { /** Is sample type WAV? **/
- unsigned numchan, align, numbits, bytechan;
- int ch;
- unsigned long cch;
-
- Gowav(pfileSample, "fmt ");
- fseek(pfileSample, 6, SEEK_CUR);
- numchan = WordRead(pfileSample); /*** Get #channels ***/
- fseek(pfileSample, 8, SEEK_CUR);
- align = WordRead(pfileSample); /*** Get block alignment (in bytes) ***/
- numbits = WordRead(pfileSample); /*** Get #bits/sample ***/
- bytechan = align / numchan; /*** Calc bytes/channel ***/
- Gowav(pfileSample, "data");
- cch = LongRead(pfileSample) / align;
- if (131072 < cch)
- cch = 131072;
- else if (cch & 1) /*** Ensure length is even ***/
- cch &= ~1;
- cSample = cch;
- while (cch--) { /*** With each sample.. ***/
- if (1 < bytechan)
- fseek(pfileSample, bytechan - 1, SEEK_CUR);
- ch = getc(pfileSample); /*** Get most sig. byte ***/
- if ((numbits > 8) == fSignout)
- putc(ch, pfileOut); /*** Output it ***/
- else
- putc(ch ^ 128, pfileOut);
- if (bytechan != align) /*** Skip any remaining channels of sample ***/
- fseek(pfileSample, align - bytechan, SEEK_CUR);
- }
-
- } else { /** Sample file must be a SMP file **/
- long cch;
- int ch;
-
- fseek(pfileSample, 0, SEEK_END);
- cch = ftell(pfileSample);
- if (131072 < cch)
- cch = 131072;
- else if (cch & 1) /** Ensure length is even **/
- cch &= ~1;
- cSample = cch;
- fseek(pfileSample, 0, SEEK_SET);
- while ((ch = getc(pfileSample)) != EOF)
- if (fSignout)
- putc(ch, pfileOut);
- else
- putc(ch ^ 128, pfileOut);
- }
- fclose(pfileSample);
- return cSample;
- }
-